# -*- coding: utf-8 -*-

import json

from django.utils.decorators import method_decorator
from django.views.decorators.http import require_POST, require_GET
from django.views.generic import TemplateView

from async.async_job import notify_mch_withdraw
from common.console import db as user_db
from common.mch import db as mch_db
from common.utils import track_logging
from common.utils.api import token_required
from common.utils.decorator import response_wrapper, safe_wrapper
from common.utils.exceptions import ParamError
from common.utils.export import redirect_to_file, gen_filename
from common.utils.tz import utc_to_local_str
from common.withdraw import db as withdraw_db
from common.withdraw import handler as withdraw_handler
from common.withdraw.admin_db import get_all_channels, get_all_channel_rate, get_channel_rate
from common.withdraw.model import WITHDRAW_ORDER_STATUS, WITHDRAW_BATCH_TYPE

_LOGGER = track_logging.getLogger(__name__)

ORDER_PREFIX = {
    'loki': 'L',
    'witch': 'W',
    'diablo': 'HLG',
    'zszs': 'Z',
    'Durotar': 'D',
    'dagent': 'DAG',
    u'泰坦': 'TT',
    # TODO: ADD ORDER PREFIX HERE
}


class WithdrawOrderView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        cond = user_db.get_mchids_filter_by_user(req.user_id)
        if cond and query_dct.get('mch_id') is None:
            query_dct['mch_id'] = cond
        mch_dct = mch_db.get_mch_dct()
        withdraw_channels = get_all_channels()
        items, total_count, total_amount = withdraw_db.list_order(query_dct)
        third_type = query_dct.get('third_type', None)
        avg_rate = get_all_channel_rate()  # 获取平均费率
        if third_type:
            avg_rate = get_channel_rate(third_type)

        resp_items = []
        for item in items:
            data = item.as_dict()
            data['created_at'] = utc_to_local_str(data['created_at'])
            data['updated_at'] = utc_to_local_str(data['updated_at'])
            data['mch_id'] = mch_dct.get(data['mch_id'], '-')
            data['third_name'] = withdraw_channels.get(data['third_type'])
            data['out_trade_no'] = ORDER_PREFIX.get(data['mch_id'], '') + str(data['out_trade_no'])
            data['id'] = str(data['id'])
            resp_items.append(data)

        return {
            'list': resp_items,
            'page': query_dct.get('$page', 1),
            'total_amount': str(total_amount),
            'total_rate': round(total_amount * avg_rate / 100.0, 2),
            'size': len(resp_items),
            'total_count': total_count
        }

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(WithdrawOrderView, self).dispatch(*args, **kwargs)


class SingleWithdrawOrderView(TemplateView):
    def get(self, req, order_id):
        order = withdraw_db.get_order(int(order_id))
        mch_dct = mch_db.get_mch_dct()
        withdraw_channels = get_all_channels()

        data = order.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['mch_id'] = mch_dct.get(data['mch_id'], '-')
        data['third_name'] = withdraw_channels.get(data['third_type'])
        data['out_trade_no'] = ORDER_PREFIX.get(data['mch_id'], '') + str(data['out_trade_no'])
        return data

    def delete(self, req, order_id):
        withdraw_db.delete_order(int(order_id))
        _LOGGER.info('delete order: %s, user: %s', order_id, req.user_id)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleWithdrawOrderView, self).dispatch(*args, **kwargs)


@require_POST
@token_required
@response_wrapper
def lock_withdraw_order(req, order_id):
    withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.LOCKED, '', req.user.username)
    return {'operation': True}


@require_POST
@token_required
@response_wrapper
@safe_wrapper
def approve_withdraw_order(req, order_id):
    data = json.loads(req.body)
    reason = data.get('detail', '')
    trans_card_name = data.get('trans_card_name', '')
    withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.DONE, reason, req.user.username,
                                              trans_card_name)
    # notify_status, _ = notify_mch_withdraw(withdraw_order)
    notify_status, _ = notify_mch_withdraw(order_id)
    return {'operation': True, 'notify': notify_status}


@require_POST
@token_required
@response_wrapper
def approve_third_withdraw_order(req, order_id):
    withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.THIRD_UNKNOWN, '第三方成功', req.user.username)
    notify_status, _ = notify_mch_withdraw(order_id)
    return {'operation': True, 'notify': notify_status}


@require_POST
@token_required
@response_wrapper
def reject_withdraw_order(req, order_id):
    data = json.loads(req.body)
    reason = data['detail']
    withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.REJECTED, reason, req.user.username)
    # notify_status, _ = notify_mch_withdraw(withdraw_order)
    notify_status, _ = notify_mch_withdraw(order_id)
    return {'operation': True, 'notify': notify_status}


@require_POST
@token_required
@response_wrapper
def notify_withdraw_order(req, order_id):
    order = withdraw_db.get_order(int(order_id))

    # 添加通知限制
    if order.status not in [WITHDRAW_ORDER_STATUS.DONE, WITHDRAW_ORDER_STATUS.REJECTED]:
        return {}

    notify_status, _ = notify_mch_withdraw(order_id)
    return {'notify': notify_status}


@require_GET
@token_required
@response_wrapper
def export_withdraw_orders(req):
    query_dct = req.GET.dict()

    mch_dct = mch_db.get_mch_dct()
    withdraw_channels = get_all_channels()
    filename = gen_filename('withdraw')
    header = ['id', 'status_cn', 'mch_id', 'user_id', 'pay_type',
              'pay_account_bank', 'pay_account_bank_subbranch', 'pay_account_num',
              'pay_account_username', 'amount', 'region', 'out_trade_no',
              'third_name', 'created_at', 'updated_at', 'notify_status',
              'notify_count', 'admin'
              ]
    cn_header = [u'订单id', u'提现状态', u'平台', u'用户ID',
                 u'支付类型', u'提现账号银行', u'提现账号支行', u'提现账号',
                 u'提现用户名', u'金额', u'客户地区', u'商户订单号', u'第三方名称',
                 u'创建订单时间', u'最后修改时间', u'回调状态', u'回调次数',
                 u'操作人'
                 ]
    items, total_count, total_amount = withdraw_db.list_order(query_dct)
    resp_items = []
    for item in items:
        data = item.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['mch_id'] = mch_dct.get(data['mch_id'], '-')
        data['third_name'] = withdraw_channels.get(data['third_type'])
        data['out_trade_no'] = ORDER_PREFIX.get(data['mch_id'], '') + str(data['out_trade_no'])
        data['id'] = str(data['id'])
        data['status_cn'] = WITHDRAW_ORDER_STATUS.get_label(int(data['status'] or 0))
        resp_items.append([data.get(x, '-') for x in header])
    return redirect_to_file(resp_items, cn_header, filename)


@require_POST
@token_required
@response_wrapper
def resend_withdraw_order(req, order_id):
    order = withdraw_db.resend_order(int(order_id))
    withdraw_handler.resend_withdraw(order)
    return {'operation': True}


@require_POST
@response_wrapper
@token_required
@safe_wrapper
def batch_withdraw_order(req):
    data = json.loads(req.body)
    _LOGGER.info('batch data: %s', data)
    orders = data['orders']
    operator = int(data['operator'])
    reason = data.get('detail', None)
    trans_card_name = data.get('trans_card_name', None)
    if len(orders) > 20:
        raise ParamError(u'批量订单最多20笔')
    # 判断order状态
    count = len(set([order['status'] for order in orders]))
    if count != 1:
        raise ParamError(u'订单状态需一致，请重新提交')

    order_ids = [order['id'] for order in orders]

    for order_id in order_ids:
        if operator == WITHDRAW_BATCH_TYPE.LOCK:
            withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.LOCKED, reason, req.user.username)
        elif operator == WITHDRAW_BATCH_TYPE.REPEAT:
            order = withdraw_db.resend_order(int(order_id))
            withdraw_handler.resend_withdraw(order)
        elif operator == WITHDRAW_BATCH_TYPE.DONE:
            withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.DONE, reason, req.user.username,
                                                      trans_card_name)
            notify_status, _ = notify_mch_withdraw(order_id)
        elif operator == WITHDRAW_BATCH_TYPE.NOTIFY:
            notify_status, _ = notify_mch_withdraw(order_id)
        elif operator == WITHDRAW_BATCH_TYPE.REJECT:
            withdraw_order = withdraw_db.update_order(order_id, WITHDRAW_ORDER_STATUS.REJECTED, reason,
                                                      req.user.username)
            notify_status, _ = notify_mch_withdraw(order_id)

    return {'operation': True}

@require_POST
@response_wrapper
@token_required
def refresh_withdraw_order(req, order_id):
    order = withdraw_db.get_order(int(order_id))
    status = withdraw_handler.query_withdraw(order)
    stat = WITHDRAW_ORDER_STATUS.get_key(status)
    return {'status': stat}